use crate::commands::list::List;
use crate::error::TodoError;
use crate::storage::Storage;
use crate::ExecuteCommand;
use anyhow::Result;
use chrono::{Duration, NaiveDate};
use clap::Parser;

#[derive(Parser, Debug)]
pub struct Delay {
    /// 要编辑的任务的 ID
    pub id: u32,

    /// 指定要延迟的天数
    #[arg(short = 'n', long)]
    pub days: Option<u32>,

    /// 指定要延迟到哪一天
    #[arg(short,long,value_parser=crate::commands::parse_date)]
    pub date: Option<NaiveDate>,

    /// 添加后展示今天的待办
    #[arg(short = 'l', long = "list")]
    pub show_list: bool,
}

impl ExecuteCommand for Delay {
    fn execute_command(&self, storage: &impl Storage) -> Result<()> {
        if self.days.is_some() && self.date.is_some() {
            return Err(TodoError::ParamError("specify days or date".to_string()))?;
        }

        if let Some(old) = storage.find_by_id(self.id)? {
            let date = self.date
                .or_else(|| add_days(old.date, self.days.unwrap_or(1)).ok()).unwrap();

            storage.update_date(self.id, &date)?;
        }

        if self.show_list {
            let list = List {
                days: None,
                status: None,
            };
            list.execute_command(storage)?;
        }

        Ok(())
    }
}

/// 计算从当前日期减去指定天数后的日期
///
/// # Arguments
///
/// * `days` - 一个 u32 类型的参数，表示要减去的天数
///
/// # Returns
///
/// * 返回一个 NaiveDate 表示减去天数后的日期
fn add_days(date: NaiveDate, days: u32) -> Result<NaiveDate> {
    // 减去指定的天数，返回新日期
    date.checked_add_signed(Duration::days(days as i64)).ok_or(TodoError::UnsupportedTimeRanges().into())
}